module utils.quaternion;

public struct Quaternion(T) {
    T x0, x1, x2, x3;

    public static Quaternion opCall(T x0, T x1, T x2, T x3) {
        Quaternion r = void;
        r.x0 = x0;
        r.x1 = x1;
        r.x2 = x2;
        r.x3 = x3;
        return r;
    }

    public Quaternion opMul(in Quaternion q) {
        Quaternion r = void;
        r.x0 = x0*q.x0 - x1*q.x1 - x2*q.x2 - x3*q.x3;
        r.x1 = x0*q.x1 + x1*q.x0 + x2*q.x3 - x3*q.x2;
        r.x2 = x0*q.x2 - x1*q.x3 + x2*q.x0 + x3*q.x1;
        r.x3 = x0*q.x3 + x1*q.x2 - x2*q.x1 + x3*q.x0;
        return r;
    }

    public Quaternion opCom() {
        Quaternion r = void;
        r.x0 = x0;
        r.x1 = -x1;
        r.x2 = -x2;
        r.x3 = -x3;
        return r;
    }
}

alias Quaternion!(float) Quaternionf;

